home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
x11
/
rpg
/
crossfir.92
/
crossfir
/
crossfire-0.92.5
/
common
/
xutil.c
< prev
Wrap
C/C++ Source or Header
|
1996-07-24
|
14KB
|
470 lines
/*
* static char *rcsid_xutil_c =
* "$Id: xutil.c,v 1.27 1996/03/04 09:28:05 master Exp $";
*/
/*
CrossFire, A Multiplayer game for X-windows
Copyright (C) 1994 Mark Wedel
Copyright (C) 1992 Frank Tore Johansen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author can be reached via e-mail to master@rahul.net
*/
#include <global.h>
#include <funcpoint.h>
#include <loader.h>
#ifdef Xpm_Pix
#include <X11/xpm.h>
#endif
/* This now merges the color alias and color name table together.
* The first entry is the color as it is referred to in objects,
* the second is the actual screen/X11 color to use. NUM_COLORS is now
* defined in global.h - if adding colors, increase that value, and everything
* else should work appropriately.
*/
char *colorname[NUM_COLORS][2] = {
{"black", "Black"}, /* 0 */
{"white", "White"}, /* 1 */
{"blue", "Navy"}, /* 2 */
{"red", "Red"}, /* 3 */
{"orange", "Orange"}, /* 4 */
{"light_blue", "DodgerBlue"}, /* 5 */
{"dark_orange", "DarkOrange2"}, /* 6 */
{"green", "SeaGreen"}, /* 7 */
{"light_green", "DarkSeaGreen"}, /* 8 - Used for window background color */
{"grey", "Grey50"}, /* 9 */
{"brown", "Sienna"}, /* 10 */
{"yellow", "Gold"}, /* 11 */
{"khaki", "Khaki"} /* 12 */
};
/*
* Converts between Fontindex and XChar2b types.
* Used in global.h, for draw_face (in face, FontindextoXChars
* is defined to this function name
*/
XChar2b fontindex_to_XChar2b(Fontindex s)
{
XChar2b c;
c.byte1 = s/256;
c.byte2 = s%256;
return c;
}
/*
* ReadPixmaps(): When color pixmaps are used instead of fonts, this function
* does the actual reading of pixmap-file. This function is based largely on
* the ReadBitmaps function. By Mark Wedel (master@rahul.net)
*/
/* New method: Pixmaps are stored as a montage on the disk (in several
* files). This way, we only need to call XCreatePixmap... a couple
* times, and the rest are XCopyArea. This is much faster, since
* the XPM library does not seem to be especially efficient about loading
* large numbers of pixmaps.
*
* Return true if we have gone to a private colormap.
*/
int ReadPixmaps(Display *gdisp, Pixmap **pixmaps, Pixmap **masks,
Colormap *cmap) {
#ifdef Xpm_Pix
int file_num, x, y, num_files, image_num=0,i, image_left, error,depth;
char buf[MAX_BUF];
Pixmap pixmap, mask;
Window root = RootWindow (gdisp,DefaultScreen(gdisp));
XpmAttributes xpmatribs;
int use_private_cmap=0;
/* This function is called before the game gc's are created. So
* we create one for our own use here.
*/
GC gc= XCreateGC(gdisp, root, 0, NULL), gc1;
if (*cmap) {
xpmatribs.valuemask = XpmColormap;
xpmatribs.colormap=*cmap;
}
else xpmatribs.valuemask=0;
/* We need a depth 1 gc. So create a depth 1 pixmap and use that */
pixmap = XCreatePixmap(gdisp, root, 1, 1, 1);
gc1= XCreateGC(gdisp, pixmap, 0, NULL);
XSetGraphicsExposures(gdisp, gc, False);
XSetGraphicsExposures(gdisp, gc1, False);
XFreePixmap(gdisp, pixmap);
depth = DefaultDepth(gdisp,DefaultScreen(gdisp));
if (!nrofpixmaps)
nrofpixmaps = ReadBmapNames ();
image_left = nrofpixmaps;
/* The processes that create a pixmap already allocates the space for
* the pixmap data. Therefor, only space for the pointers to that data
* needs to be allocated. The same might apply for the function
* that creates bitmaps below, but I am not as sure in that case.
* Mark Wedel (master@rahul.net)
*/
*pixmaps = (Pixmap *) malloc(sizeof(Pixmap *) * nrofpixmaps);
*masks = (Pixmap *) malloc(sizeof(Pixmap *) * nrofpixmaps);
for (i=0; i < nrofpixmaps; i++)
(*pixmaps)[i] = 0;
num_files = nrofpixmaps/ (XPM_MONTAGE_X * XPM_MONTAGE_Y);
if (nrofpixmaps % (XPM_MONTAGE_X * XPM_MONTAGE_Y)) num_files ++;
LOG(llevDebug,"Building color pixmaps...");
for (file_num=1; file_num<=num_files; file_num++) {
sprintf (buf,"%s/%s.pix.%d",LIBDIR, FONTNAME,file_num);
again: error=XpmReadFileToPixmap(gdisp, root,
buf,&pixmap,&mask, &xpmatribs);
if (error!=XpmSuccess) {
if (error==XpmColorFailed && !use_private_cmap) {
LOG(llevError,"XPM could not allocate colors - trying to switch to private colormap\n");
*cmap=XCopyColormapAndFree(gdisp, *cmap);
xpmatribs.colormap=*cmap;
use_private_cmap=1;
goto again;
}
LOG(llevError,"Error creating pixmap %s, error %d.\n",buf, error);
}
else do {
x=0;
y=0;
for (i=0; i< (XPM_MONTAGE_X * XPM_MONTAGE_Y); i++) {
if((*pixmaps)[image_num] != 0)
LOG(llevError,"Warning: two entries in bmaps: %d\n",i);
else {
(*pixmaps)[image_num] = XCreatePixmap(
gdisp, root, 24, 24, depth);
(*masks)[image_num] = XCreatePixmap(
gdisp, root, 24, 24, 1);
XCopyArea(gdisp, pixmap, (*pixmaps)[image_num],
gc, x*24, y*24, 24, 24, 0, 0);
XCopyArea(gdisp, mask, (*masks)[image_num],
gc1, x*24, y*24, 24, 24, 0, 0);
}
x++;
if (x==XPM_MONTAGE_X) {
y++;
x=0;
}
image_num++;
image_left--;
if (!image_left) break;
if(!(image_num % (CHECK_ACTIVE_MAPS/10))) {
LOG(llevDebug,".");
(*process_active_maps_func)(); /* Process active maps as often as possible */
}
}
} while (image_num<nroffiles && (image_num % (XPM_MONTAGE_X * XPM_MONTAGE_Y)));
XFreePixmap(gdisp, pixmap);
XFreePixmap(gdisp, mask);
}
XFreeGC(gdisp, gc);
XFreeGC(gdisp, gc1);
/* Check for any holes. There should not be. This is an interim check
* to use until the xbm_values is removed. The program that
* creates the bitmap/pixmap files just adds the bitmaps, so holes should
* not be in the image file.
*/
for (i = 0; i < nrofpixmaps; i++)
if ((*pixmaps)[i] == 0) {
LOG(llevDebug, "Warning, pixmap %d is not defined, setting it to blank\n", i);
pixmaps[i] = pixmaps[blank_face->number];
}
return use_private_cmap;
#else
return 0; /* Prevents some warning messages */
#endif
}
/* This frees all the pixmaps. This not only makes for better code,
* some XServers may not free the memory used by the pixmaps unless it is done
* this way. For color pixmaps, this will be called twice - the
* first time, the normal pixmaps will be passed through, the second
* time, it will be called with the masks as the pixmaps argument.
*/
void free_pixmaps(Display *gdisp, Pixmap *pixmaps)
{
int i;
for (i=0; i < nrofpixmaps; i++) {
if (pixmaps[i]!=0) {
XFreePixmap(gdisp, pixmaps[i]);
pixmaps[i] = 0;
}
}
}
/*
* ReadBitmaps(): When bitmaps are used instead of fonts, this function
* does the actual reading of bitmap-file, and returns the
* bitmaps array. It assumes the bitmap file found in the LIBDIR
* directory.
*/
Pixmap *ReadBitmaps(Display *d) {
char buf[MAX_BUF];
FILE *fp;
int i, count = 0,comp;
Pixmap *pixmaps;
if (!nrofpixmaps)
nrofpixmaps = ReadBmapNames ();
pixmaps = (Pixmap *) malloc(sizeof(Pixmap) * nrofpixmaps);
for (i=0; i < nrofpixmaps; i++)
pixmaps[i] = 0;
sprintf (buf,"%s/%s.cfb",LIBDIR, FONTNAME);
if ((fp = open_and_uncompress(buf,0,&comp))==NULL) {
perror("Can't open crossfire.cfb file");
exit(-1);
}
LOG(llevDebug,"Building ximages...");
for (i=0; i<nroffiles; i++) {
if(pixmaps[i] != 0) {
LOG(llevError,"Warning: two entries in bmaps: %d\n",i);
continue;
}
if (fread (buf, 24 * 3, 1, fp) != 1) {
LOG(llevError,"Warning: cannot read from file\n");
break;
}
pixmaps[i] = XCreateBitmapFromData
(d, RootWindow (d, DefaultScreen(d)), buf, 24, 24);
if (!pixmaps[i]) {
LOG(llevError,"Warning: Cannot create Pixmap %d\n",i);
pixmaps[i] = 0;
}
if(++count > CHECK_ACTIVE_MAPS/10) {
printf (".");
fflush (stdout);
count = 0;
(*process_active_maps_func)();
}
}
close_and_delete(fp, comp);
LOG(llevDebug,"done\n");
/*
* Now fill out the unused holes with pointers to a blank pixmap
* to avoid crashes in case trying to draw a nonexistant pixmap.
*/
for (i = 0; i < nrofpixmaps; i++)
if (pixmaps[i] == 0)
pixmaps[i] = pixmaps[blank_face->number];
return pixmaps;
}
/*
* This function adds the path to the fontpath of the given display.
* It's mostly copied from the X11R5 distribution.
*/
void set_font_path(Display *dpy, char *path) {
char **currentList = NULL; int ncurrent = 0;
char **directoryList = NULL; int ndirs = 0;
currentList = XGetFontPath (dpy, &ncurrent);
if(currentList==NULL) {
LOG(llevError,"Unable to get old font path.\n");
return;
}
{
register char *cp = path;
ndirs=1;
while((cp=strchr(cp, ','))!=NULL)
ndirs++,cp++;
directoryList=(char **) malloc(ndirs*sizeof(char *));
if(!directoryList) {
LOG(llevError,"Unable to allocate memory for font path directory.\n");
return;
}
}
{
int i=0;
char *cp = path;
directoryList[i++]=cp;
while((cp=strchr(cp, ','))!=NULL)
directoryList[i++]=cp+1,
*cp++='\0';
if(i!=ndirs) {
LOG(llevError,"Internal error, only parsed %d of %d dirs.\n",i,ndirs);
return;
}
}
{
int nnew=ndirs+ncurrent;
char **newList = (char **) malloc (nnew * sizeof(char *));
if(!newList) {
LOG(llevError,"Couldn't get memory for new fontpath.\n");
return;
}
/* #if defined(SYSV) || defined(SVR4) */
memcpy((void *)newList,(void *)directoryList,
(unsigned) (ndirs*sizeof (char *)));
memcpy((void *) (newList + ndirs), (void *) currentList,
(unsigned) (ncurrent*sizeof (char *)));
XSetFontPath(dpy,newList, nnew);
free((char *)newList);
}
if (directoryList)
free((char *) directoryList);
if (currentList)
XFreeFontPath (currentList);
}
/*
* Checks if "crossfire" is present somewhere in the fontpath of
* the given display.
*/
int check_font_path(Display *dpy) {
int count;
char **list;
list = XListFonts(dpy, font_graphic, 1, &count);
LOG(llevDebug, "Matching fonts to %s: %d (%s)\n",
font_graphic,count,count?*list:"");
XFreeFontNames(list);
return count;
}
/*
* Uses check_font_path() and set_font_path() to check and, if needed
* fix the fontpath for the player.
* Function changed around to make it useful for the client.
* Passing the player struct to this is not required - xio.c
* can use the return value to set the use_pixmaps value in the
* player struct. name is only passed to give better error
* messages.
*/
int fixfontpath(Display *disp, char *name) {
if (check_font_path(disp))
return 0;
if(fix_fontpath) {
LOG(llevError,"Trying to fix fontpath for display %s.\n",name);
fflush(logfile);
set_font_path(disp,FontDir);
if(check_font_path(disp))
return 0;
}
LOG(llevError,"Failed, switching to pixmaps (this might take a while).\n");
sprintf(errmsg,"Display %s doesn't have the right fontpath.",name);
return 1;
}
/*
* allocate_colors() tries to get enough colors for the game-window.
* If it fails, it tries to use a private colormap.
* If that also fails, it return 1, indicating to the calling
* function that black and white should be used.
*
* Function arguments became a bit more complicated in v0.91.5.
* The functionality is the same, but instead of passing the player
* structure, just pass the values that are needed. This enables
* the new client to use the function also.
*
* Original function by Tyler Van Gorder (tvangod@icst.csuchico.edu),
* June 1, 1992
*/
int allocate_colors(Display *disp, Window w, long screen_num,
Colormap *colormap, XColor discolor[NUM_COLORS])
{
int i, tried = 0, depth=0, iscolor;
Status status;
Visual *vis;
XColor exactcolor;
if(no_color) {
return 0;
}
iscolor = 1;
vis = DefaultVisual(disp,screen_num);
if (vis->class >= StaticColor) {
*colormap = DefaultColormap(disp,screen_num);
depth = DefaultDepth(disp,screen_num);
}
else {
*colormap=(Colormap )NULL;
LOG(llevError,"Switching to black and white.\n");
LOG(llevError,"You have a black and white terminal.\n");
return 0;
}
try_private:
if (depth > 3 && iscolor) {
unsigned long pixels[13];
for (i=0; i<13; i++){
status = XLookupColor(disp,*colormap, colorname[i][1],&exactcolor,
&discolor[i]);
if (!status){
LOG(llevError,"Can't find colour %s.\n", colorname[i]);
LOG(llevError,"Switching to black and white.\n");
iscolor = 0;
break;
}
status = XAllocColor(disp,*colormap,&discolor[i]);
if (!status) {
if (!tried) {
LOG(llevError, "Not enough colours. Trying a private colourmap.\n");
XFreeColors(disp, *colormap, pixels, i-1, 0);
*colormap = XCreateColormap(disp, w, vis, AllocNone);
XSetWindowColormap(disp, w, *colormap);
tried = 1;
goto try_private;
} else {
LOG(llevError, "Failed. Switching to black and white.\n");
iscolor = 0;
break;
}
}
pixels[i] = discolor[i].pixel;
}
}
return iscolor;
}